<html>
<head>
    <title>Canvas小练习</title>
    <meta charset="UTF-8">
    <style type="text/css">
        canvas {
            border: 1px solid black;
        }
    </style>
    <script src="//cdn.66173.cn/www/js/jquery-1.8.3.min.js"></script>
</head>
    <canvas id="tutorial" width="300" height="300"></canvas>
    <canvas id="tutorial2" width="300" height="300"></canvas>
    <canvas id="tutorial3" width="300" height="300"></canvas>
    <canvas id="tutorial4" width="300" height="300"></canvas>
    <canvas id="tutorial5" width="300" height="300"></canvas>
    <canvas id="tutorial6" width="300" height="300"></canvas>
    <div style="width: 100%;height: 300px;">
        <canvas id="tutorial7" width="300" height="300"></canvas>
        <canvas id="tutorial8" width="300" height="300"></canvas>
        <canvas id="tutorial9" width="300" height="300"></canvas>
        <canvas id="tutorial10" width="300" height="300"></canvas>
        <canvas id="tutorial11" width="300" height="300"></canvas>
        <canvas id="tutorial12" width="300" height="300"></canvas>
    </div>
    <div style="width: 100%;height: 300px;;margin-top: 5px">
        <canvas id="tutorial13" width="300" height="300"></canvas>
        <canvas id="tutorial14" width="300" height="300"></canvas>
        <canvas id="tutorial15" width="300" height="300"></canvas>
        <canvas id="tutorial16" width="300" height="300"></canvas>
        <canvas id="tutorial17" width="300" height="300"></canvas>
        <canvas id="tutorial18" width="300" height="300"></canvas>
    </div>
<div style="width: 100%;height: 300px;;margin-top: 5px">
    <canvas id="tutorial19" width="300" height="300"></canvas>
    <canvas id="tutorial20" width="300" height="300"></canvas>
    <canvas id="tutorial21" width="300" height="300"></canvas>
    <canvas id="tutorial22" width="300" height="300"></canvas>
    <canvas id="tutorial23" width="300" height="300"></canvas>
    <canvas id="tutorial24" width="300" height="300"></canvas>
</div>
<!--<img src="http://img.shein.com/images2/2018/05/09/15258522023136879796.png" width="300" height="300" id="img-change">-->
</body>
<!--绘制矩形-->
<script type="text/javascript">
    function draw(){
        var canvas = document.getElementById('tutorial');
        if(!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "rgb(200,0,0)";
        //绘制矩形
        ctx.fillRect (30, 10, 55, 50);

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.fillRect (30, 70, 55, 50);
        ctx.clearRect(45, 20, 25, 25)
    }
    draw();
</script>
<!--绘制线段-->
<script type="text/javascript">
    function draw2(){
        var canvas = document.getElementById('tutorial2');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath(); //新建一条path
        ctx.moveTo(50, 50); //把画笔移动到指定的坐标
        ctx.lineTo(200, 90);  //绘制一条从当前位置到指定坐标(200, 50)的直线.
        //闭合路径。会拉一条从当前点到path起始点的直线。如果当前点与起始点重合，则什么都不做
        ctx.closePath();
        ctx.stroke(); //绘制路径。
    }
    draw2();
</script>
<!--绘制三角形-->
<script type="text/javascript">
    function draw3(){
        var canvas = document.getElementById('tutorial3');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(50, 50);
        ctx.lineTo(200, 150);
        ctx.lineTo(200, 200);
        ctx.lineTo(50, 200);
        ctx.closePath(); //虽然我们只绘制了两条线段，但是closePath会closePath，仍然是一个3角形
        ctx.stroke(); //描边。stroke不会自动closePath()
        ctx.fill();
    }
    draw3();
</script>
<!--绘制圆弧-->
<script type="text/javascript">
    function draw4(){
        var canvas = document.getElementById('tutorial4');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.arc(150, 150, 40, 0, 2*Math.PI, false);
        ctx.stroke();
    }
    draw4();
</script>
<!--圆弧案例2-->
<script>
    function draw5(){
        var canvas = document.getElementById('tutorial5');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.arc(50, 50, 40, 0, Math.PI / 2, false);
        ctx.stroke();

        ctx.beginPath();
        ctx.arc(150, 50, 40, 0, -Math.PI / 2, true);
        ctx.closePath();
        ctx.stroke();

        ctx.fillStyle = "rgba(0, 0, 200, 0.5)";
        ctx.beginPath();
        ctx.arc(50, 150, 40, -Math.PI / 2, Math.PI, false);
        ctx.fill();

        ctx.fillStyle = "rgba(210, 0, 400, 0.5)";
        ctx.beginPath();
        ctx.arc(150, 150, 40, 0, 2*Math.PI, false);
        ctx.fill();

    }
    draw5();
</script>
<!--圆弧案例3-->
<script>
    function draw6(){
        var canvas = document.getElementById('tutorial6');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(50, 50);
        //参数1、2：控制点1坐标   参数3、4：控制点2坐标  参数4：圆弧半径
        ctx.arcTo(200, 50, 200, 200, 80);
        ctx.lineTo(200, 200)
        ctx.closePath();
        ctx.stroke();//描边。stroke不会自动closePath()

        ctx.beginPath();
        ctx.rect(50, 50, 10, 10);
        ctx.rect(200, 50, 10, 10)
        ctx.rect(200, 200, 10, 10)
        ctx.fill()
    }
    draw6();
</script>
<!--绘制二次贝塞尔曲线-->
<script>
    function draw7(){
        var canvas = document.getElementById('tutorial7');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(10, 200); //起始点
        var cp1x = 40, cp1y = 100;  //控制点
        var x = 200, y = 200; // 结束点
        //绘制二次贝塞尔曲线
        ctx.quadraticCurveTo(cp1x, cp1y, x, y);
        ctx.stroke();

        ctx.beginPath();
        ctx.rect(10, 200, 10, 10);
        ctx.rect(cp1x, cp1y, 10, 10);
        ctx.rect(x, y, 10, 10);
        ctx.fill();

    }
    draw7();
</script>
<!--绘制三次贝塞尔曲线-->
<script>
    function draw8(){
        var canvas = document.getElementById('tutorial8');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.beginPath();
        ctx.moveTo(40, 200); //起始点
        var cp1x = 20, cp1y = 100;  //控制点1
        var cp2x = 100, cp2y = 120;  //控制点2
        var x = 200, y = 200; // 结束点
        //绘制二次贝塞尔曲线
        ctx.bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y);
        ctx.stroke();
        ctx.fillStyle ="red"

        ctx.beginPath();

        ctx.rect(40, 200, 10, 10);
        ctx.rect(cp1x, cp1y, 10, 10);
        ctx.rect(cp2x, cp2y, 10, 10);
        ctx.rect(x, y, 10, 10);
        ctx.fill();
        ctx.strokeStyle ="blue"
    }
    draw8();
</script>
<script>
    function draw9(){
        var canvas = document.getElementById('tutorial9');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        for (var i = 0; i < 6; i++){
            for (var j = 0; j < 6; j++){
                ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ',' +
                    Math.floor(255 - 42.5 * j) + ',0)';
                ctx.fillRect(j * 50, i * 50, 50, 50);
            }
        }
    }
    draw9();
</script>
<script type="text/javascript">
    function draw10(){
        var canvas = document.getElementById('tutorial10');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        for (var i = 0; i < 6; i++){
            for (var j = 0; j < 6; j++){
                ctx.strokeStyle = `rgb(${randomInt(0, 255)},${randomInt(0, 255)},${randomInt(0, 255)})`;
                ctx.strokeRect(j * 50, i * 50, 40, 40);
            }
        }
    }
    draw10();
    /**
     返回随机的 [from, to] 之间的整数(包括from，也包括to)
     */
    function randomInt(from, to){
        return parseInt(Math.random() * (to - from + 1) + from);
    }

</script>
<script>
    function draw11(){
        var canvas = document.getElementById('tutorial11');
        var lineCaps = ["butt", "round", "square"];
        var ctx = canvas.getContext("2d");
        for (var i = 0; i < 3; i++){
            ctx.beginPath();
            ctx.moveTo(20 + 30 * i, 30);
            ctx.lineTo(20 + 30 * i, 100);
            ctx.lineWidth = 20;
            ctx.lineCap = lineCaps[i];
            ctx.stroke();
        }

        ctx.beginPath();
        ctx.moveTo(0, 30);
        ctx.lineTo(300, 30);

        ctx.moveTo(0, 100);
        ctx.lineTo(300, 100)

        ctx.strokeStyle = "red";
        ctx.lineWidth = 1;
        ctx.stroke();
    }
    draw11();
</script>
<!--菱形区域-->
<script>
    function draw12(){
        var canvas = document.getElementById('tutorial12');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");

        var lineJoin = ['round', 'bevel', 'miter'];
        ctx.lineWidth = 20;

        for (var i = 0; i < lineJoin.length; i++){
            ctx.lineJoin = lineJoin[i];
            ctx.beginPath();
            ctx.moveTo(50, 50 + i * 50);
            ctx.lineTo(100, 100 + i * 50);
            ctx.lineTo(150, 50 + i * 50);
            ctx.lineTo(200, 100 + i * 50);
            ctx.lineTo(250, 50 + i * 50);
            ctx.stroke();
        }
    }
    draw12();
</script>
<!--绘制虚线-->
<script>
    function draw13(){
        var canvas = document.getElementById('tutorial13');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");

        ctx.setLineDash([20, 5]);  // [实线长度, 间隙长度]
        ctx.lineDashOffset = -0;
        ctx.strokeRect(50, 50, 210, 210);
    }
    draw13();
</script>
<!--绘制字体-->
<script>
    var ctx;
    function draw(){
        var canvas = document.getElementById('tutorial14');
        if (!canvas.getContext) return;
        ctx = canvas.getContext("2d");
        ctx.font = "50px sans-serif"
        ctx.textBaseline="hanging"
        ctx.fillText("熊大最帅", 50, 100);
        ctx.strokeText("熊二可爱", 50, 200)
    }
    draw();
</script>
<!--绘制图片放大缩小切片等-->
<script type="text/javascript">
    function drawImg(){
        var canvas = document.getElementById('tutorial15');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        var img = document.querySelector("img");
        ctx.drawImage(img, 50, 50,200,200,100,100,100,100);
    }
    $("img").click(function (){
        drawImg();
    })
</script>
<!--绘制旋转和translate-->
<script>
    function draw16(){
        var canvas = document.getElementById('tutorial16');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");

        ctx.fillStyle = "red";
        ctx.save();

        ctx.translate(100, 100);
        ctx.rotate(Math.PI / 180 * 7);
        ctx.scale(1.5, 1)
        ctx.fillStyle = "blue";
        ctx.fillRect(0, 0, 100, 100);
        ctx.restore();

        ctx.save();
        ctx.translate(0, 0);
        ctx.fillRect(0, 0, 50, 50)

        ctx.restore();
    }
    draw16();
</script>
<!--变换矩阵-->
<script>
    function draw17(){
        var canvas = document.getElementById('tutorial17');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");
        ctx.fillStyle = "red";
        ctx.transform(1,0, 1, 1, 0, 0);
        ctx.fillRect(0, 0, 100, 100);

    }
    draw17();
</script>
<script>
    function draw18(){
        var canvas = document.getElementById('tutorial18');
        if (!canvas.getContext) return;
        var ctx = canvas.getContext("2d");

        ctx.beginPath();
        ctx.arc(20,20, 100, 0, Math.PI/2);
        ctx.clip();

        ctx.fillStyle = "green";
        ctx.fillRect(10, 20, 70,70);
    }
    draw18();
</script>
<!--======================================================高级实战案例1=======================================================-->
<script>
    let sun;
    let earth;
    let moon;
    function init(){
        sun = new Image();
        earth = new Image();
        moon = new Image();
        sun.src = "./sun.png";
        earth.src = "./earth.png";
        moon.src = "./yueliang.png";

        let canvas = document.querySelector("#tutorial19");
        ctx = canvas.getContext("2d");

        sun.onload = function (){
            draw19()
        }

    }
    init();
    function draw19(){
        ctx.clearRect(0, 0, 300, 300); //清空所有的内容
        /*绘制 太阳*/
        ctx.drawImage(sun, 0, 0, 300, 300);

        ctx.save();
        ctx.translate(150, 150);

        //绘制earth轨道
        ctx.beginPath();
        ctx.strokeStyle = "blue";
        ctx.arc(0, 0,100, 0, 2 * Math.PI)
        ctx.stroke()

        let time = new Date();
        //绘制地球
        ctx.rotate(2 * Math.PI / 60 * time.getSeconds() + 2 * Math.PI / 60000 * time.getMilliseconds())
        ctx.translate(100, 0);
        ctx.drawImage(earth, -18, 0.1,30,30)

        //绘制月球轨道
        ctx.beginPath();
        ctx.strokeStyle = "red";
        ctx.arc(0, 0, 40, 0, 2 * Math.PI);
        ctx.stroke();

        //绘制月球
        ctx.rotate(2 * Math.PI / 6 * time.getSeconds() + 2 * Math.PI / 6000 * time.getMilliseconds());
        ctx.translate(40, 0);
        ctx.drawImage(moon, -8, 15,10,10);
        ctx.restore();

        requestAnimationFrame(draw19);
    }
</script>
<!--======================================================高级实战案例2=======================================================-->
<script>
    init();

    function init(){
        let canvas = document.querySelector("#tutorial20");
        let ctx = canvas.getContext("2d");
        draw(ctx);
    }
    function draw(ctx){
        requestAnimationFrame(function step(){
            drawDial(ctx); //绘制表盘
            drawAllHands(ctx); //绘制时分秒针
            requestAnimationFrame(step);
        });
    }
    /*绘制时分秒针*/
    function drawAllHands(ctx){
        let time = new Date();

        let s = time.getSeconds();
        let m = time.getMinutes();
        let h = time.getHours();

        let pi = Math.PI;
        let secondAngle = pi / 180 * 6 * s;  //计算出来s针的弧度
        let minuteAngle = pi / 180 * 6 * m + secondAngle / 60;  //计算出来分针的弧度
        let hourAngle = pi / 180 * 30 * h + minuteAngle / 12;  //计算出来时针的弧度

        drawHand(hourAngle, 60, 6, "red", ctx);  //绘制时针
        drawHand(minuteAngle, 106, 4, "green", ctx);  //绘制分针
        drawHand(secondAngle, 129, 2, "blue", ctx);  //绘制秒针
    }
    /*绘制时针、或分针、或秒针
     * 参数1：要绘制的针的角度
     * 参数2：要绘制的针的长度
     * 参数3：要绘制的针的宽度
     * 参数4：要绘制的针的颜色
     * 参数4：ctx
     * */
    function drawHand(angle, len, width, color, ctx){
        ctx.save();
        ctx.translate(150, 150); //把坐标轴的远点平移到原来的中心
        ctx.rotate(-Math.PI / 2 + angle);  //旋转坐标轴。 x轴就是针的角度
        ctx.beginPath();
        ctx.moveTo(-4, 0);
        ctx.lineTo(len, 0);  // 沿着x轴绘制针
        ctx.lineWidth = width;
        ctx.strokeStyle = color;
        ctx.lineCap = "round";
        ctx.stroke();
        ctx.closePath();
        ctx.restore();
    }

    /*绘制表盘*/
    function drawDial(ctx){
        let pi = Math.PI;

        ctx.clearRect(0, 0, 300, 300); //清除所有内容
        ctx.save();
        ctx.translate(150, 150); //一定坐标原点到原来的中心
        ctx.beginPath();
        ctx.strokeStyle="green";
        ctx.arc(0, 0, 126, 0, 2 * pi); //绘制圆周
        ctx.stroke();
        ctx.closePath();

        for (let i = 0; i < 60; i++){//绘制刻度。
            ctx.save();
            ctx.rotate(-pi / 2 + i * pi / 30);  //旋转坐标轴。坐标轴x的正方形从 向上开始算起
            ctx.beginPath();
            ctx.moveTo(100, 0);
            ctx.lineTo(125, 0);
            ctx.lineWidth = i % 5 ? 1 : 4;
            ctx.strokeStyle = i % 5 ? "blue" : "red";
            ctx.stroke();
            ctx.closePath();
            ctx.restore();
        }
        ctx.restore();
    }
</script>
</html>